#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import os
import sys
import argparse

from watchdog.observers import Observer
from watchdog.events import (FileSystemEventHandler, FileModifiedEvent)

import logging
from ctools.logext import *

_rlog, _plog, _mlog, _tlog = get_loggers(__file__, __name__, propagate=False)

_fpath = os.path.dirname(os.path.realpath(__file__))

_INFO = Styler(F_GREEN)

class BaseFileWatcher(Observer):
    def __init__(self, filename="", check_level=1):
        super().__init__()

        self.filename = filename

        self.check_level = check_level
        self._filestat = os.stat(self.filename)

        self.__changed_count = 0
        self._running = False

        self._hashv = 0
        if check_level >= 2:
            with open(self.filename, 'rb') as fd:
                self._hashv = hash(fd.read())

        handler = FileSystemEventHandler()
        handler.on_modified = self._on_modified_wrapper
        pathname = self.filename if self.filename else '.'
        self.schedule(handler, path=pathname, recursive=False,
                      event_filter=[FileModifiedEvent,])

    @property
    def changed_count(self):
        return self.__changed_count


    def __del__(self):
        self.stop_work()
        # super().__del__()

    def _check_event(self, event):
        if event.is_directory:
            return False

        if self.filename == '':
            return True
        # file may not exist, can not use os.path.samefile
        elif os.path.realpath(self.filename) == os.path.realpath(event.src_path):
            return True

        return False

    def _check_changed(self):
        ret = False
        try:
            ret = False
            new_stat = os.stat(self.filename)
            if new_stat.st_mtime > self._filestat.st_mtime:
                ret = True
            if ret and self.check_level < 1:
                return True

            if new_stat.st_size != self._filestat.st_size:
                ret = True
            if ret and self.check_level < 2:
                return True

            with open(self.filename, 'r', encoding='utf-8') as fd:
                hashv = hash(fd.read())
                if hashv != self._hashv:
                    ret = True
                    self._hashv = hashv

            return ret

        except Exception as e:
            raise e
        finally:
            if ret:
                self.__changed_count += 1
                self._filestat = new_stat
            return ret

    def _on_modified_wrapper(self, event):
        if not self._check_event(event):
            return
        if not self._check_changed():
            return
        self._on_modified()

    def _on_modified(self):
        print(_INFO(f'file {self.filename} changed'))

    def start_work(self):
        if self._running:
            return
        self.start()
        self._running = True

    def stop_work(self):
        if not self._running:
            return
        self._running = False
        self.stop()
        self.join()
